// Code written by Dennis Frie for diyosd
// changed by Stefan Muerzl (stefan [dot] muerzl [at] gmail.com) to add data to line 21
// ported to plain C by Steffen Kristoph Metze (metzelmaennchen [at] gmail [dot] com)
//http://www.phecap.nl/download/enhenced-teletext-specs.pdf

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>

#define align_text 44
#define VbiDataline 30		//only for debug, DEFAULT: 21
#define SPI_DIVIDER 32 
/*
32 = 500kHz
16 = 1MHz
8 = 2MHz
4 = 4MHz
*/

#define DimOn  DDRB |= 0b00000001;
#define DimOff DDRB &= 0b11111110;

#include <avr/delay.h>


uint8_t line = 0;
uint8_t loopcount = 0;


static inline void detectline() {
        
    // ============================================================
    // Data-Insert
    // ============================================================ 
    if (line > VbiDataline && line < (VbiDataline+30)) {      
        _delay_loop_1(align_text);

        DimOn;

        // Shift out first 8 bit
        SPDR = 'A';	//A
        while (!(SPSR & (1<<SPIF)))  {     // Wait for the end of the transmission
        };

        // Shift out second 8 bit
        SPDR = 0b00000000;	//empty                   
        while (!(SPSR & (1<<SPIF)))  {     // Wait for the end of the transmission
        };	

        // Shift out third 8 bit
        SPDR = '1';	//A	 
        while (!(SPSR & (1<<SPIF)))  {     // Wait for the end of the transmission
        };	
        SPDR = 0b00000000;

        DimOff;
    }

    // Let's make sure SPI is not idling high.
    SPDR=0b00000000;

    // ============================================================
    // Data-Insert
    // ============================================================  
    if (line == 200) {
        loopcount++;		//loopcount only used to see atmega is running or not
    }
    
    if(line <= 200)
    {
        // Increase line count..
        line++;
    }
}


// Analog comparator interrupt:
ISR(ANALOG_COMP_vect) {
    // Reset counter
    TCNT2 =0; 

    // Wait for the sync to go high again;
    while ((ACSR & 0b00100000) == 0b00100000) { }  

    // If the counter has exceeded the "new line sync time", it's a new 
    // frame. In that case, we just need to reset the line-counter.  
    // 
    if (TCNT2 > 75) {
        line = 0;
    }  

    detectline(); 
}

int main()
{

// TODO check which of these ports really need to be enabled
#if 0
    pinMode(10,OUTPUT);
    pinMode(11,OUTPUT);  
    pinMode(12,OUTPUT);
    pinMode(13,OUTPUT);

    pinMode(0,INPUT);  
    pinMode(1,INPUT);
    pinMode(2,INPUT);
    pinMode(3,INPUT);
    pinMode(4,INPUT);  
    pinMode(5,INPUT);
    pinMode(6,INPUT); 
    pinMode(7,INPUT);
    pinMode(8,INPUT);  
    pinMode(9,INPUT);
#endif

    // PB5 as output for our led, arduino onboard led
    DDRB |= _BV(PB5); 
 
#if SPI_DIVIDER == 32// Set SPI to 500kHz
    SPCR = (0<<SPIE)|(1<<SPE) |(0<<DORD)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR1)|(0<<SPR0);
    SPSR = (1<<SPI2X); 
#endif 
#if SPI_DIVIDER == 16// Set SPI to 1MHz
    SPCR = (0<<SPIE)|(1<<SPE) |(0<<DORD)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(0<<SPR1)|(1<<SPR0);
    SPSR = (0<<SPI2X); 
#endif 
#if SPI_DIVIDER == 8// Set SPI to 2MHz
    SPCR = (0<<SPIE)|(1<<SPE) |(0<<DORD)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(0<<SPR1)|(1<<SPR0);
    SPSR = (1<<SPI2X); 
#endif 
#if SPI_DIVIDER == 4// Set SPI to 4MHz
    SPCR = (0<<SPIE)|(1<<SPE) |(0<<DORD)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(0<<SPR1)|(0<<SPR0);
    SPSR = (0<<SPI2X);  
#endif 

    SPDR =0b00000000;  // IMPORTANT.. The SPI will idle random at low or high in the beginning. 
  
    TIMSK0=0;
    TIMSK1=0;
    TIMSK2=0;

    // Init analog comparator to register new line and frame
    ADCSRB = 0b00000001; // Set analog comparator mode
  
    ACSR = 0b00001011; //Enable Analog comparator interrupt 
    // Set interrupt on falling output edge.
  
    ADCSRA|=(1<<ADSC);    
  
    // Start timer 2 - used to determine if it's a new frame or line. 
    TCCR2B = (0<<CS22) | //Prescale 1024
             (0<<CS21) | //Prescale 1024
             (1<<CS20) | //Prescale 1024
             (0<<WGM22); // CTC mode (Clear timer on compare match)  


    while(1) {
        //toogle a led to see that it's running
		if (loopcount > 5){
            loopcount = 0;
            PORTB ^= _BV(PB5);
        }
    }
    return 0;
}

